import { request } from "@/utils/axios";
import { appAction } from "@/store/app";
import { v4 } from "uuid";
import { ElNotification } from "element-plus";
import { FILE_URL } from "@/config";

/**
 * 通用获取数据
 */
export function queryGet(para: {
  docType: string;
  actionType?: string;
  /**
   * 返回数据方式
   */
  apiType: "SingleList" | "Single" | "PageList";
  /**
   * 页数
   */
  start?: number;
  /**
   * 每页数量
   */
  limit?: number;
}, data?: any): Promise<any> {
  return new Promise((resolve, reject) => {

    let formData: any = {
      "DocType": para.docType,
      "ActionType": para.actionType,
      "ApiType": para.apiType,
    }

    switch (para.apiType) {
      /**
       * 分页数据单独处理
       */
      case "PageList": {
        formData["Start"] = para.start;
        formData["Limit"] = para.limit || 25;
        break;
      }
    }
    request("/DoAction/Exec", Object.assign(formData, data))
      .then((res) => {
        switch (para.apiType) {
          /**
           * 单对象
           */
          case "Single": {
            resolve(res || {});
            break;
          }
          /**
           * 列表
           */
          case "SingleList": {
            resolve(res || []);
            break;
          }
          /**
           * 分页列表
           */
          case "PageList": {
            resolve({
              List: res.List || [],
              Total: res.Total || 0
            });
            break;
          }
          default: {
            resolve(res);
          }
        }
      })
      .catch(reject)
  })
}



/**
 * 上传文件接口
 */
export function uploadFile(file: File, docType: string, {
  actionType = "",
  /**
   * 是否启动图片专用上传接口
   * 图片专用上传接口会压缩图片
   */
  isImage = false
} = {}): Promise<{
  /**
   * 文件文件
   */
  fileName: string;
  /**
   * 文件大小
   */
  fileSize: string;
  /**
   * 文件全链接
   */
  fileUrl: string;
  /**
   * 文件唯一值 , 用于访问文件的
   */
  fileEntity: string;
  /**
   * 文件的后缀名
   */
  fileExtension: string
}> {
  let formData = new FormData();

  formData.append("DocType", docType);
  formData.append("ActionType", actionType);
  formData.append("IsCompress", isImage ? 'true' : '');

  //添加文件
  formData.append("file", file);
  return new Promise((resolve, reject) => {
    request("/File/Upload", formData, {
      contentType: "form",
      state: Date.now() + ""
    })
      .then(res => {
        resolve({
          fileName: res[0].FileName,
          fileSize: res[0].FileLength,
          fileEntity: res[0].FileEntity,
          fileUrl: FILE_URL + res[0].FileEntity,
          fileExtension: res[0].FileExtension,
        })
      })
      .catch(reject)
  })

}

/**
 * 切片上传
 */
export function uploadSectionFile(file: File, docType: string, {
  actionType = "",
  /**
   * 是否启动图片专用上传接口
   * 图片专用上传接口会压缩图片
   */
  isImage = false,
  /**
   *分片大小 默认2  单位m
   */
  inSize = 0.5,
  /**
   * 并行上传序列,这里最大就是6,因为,浏览器有限制,最多只能有6个并行的请求,
   * 但是这里不建议使用6个,会导致抢占了浏览器全部的并行请求,使其他请求一直被阻塞
   */
  parallelCount = 1,

  /**
   * 上传进度\
   * bfb:百分比
   * all:全部上传数量
   * index:现在是第几个
   */
  onUploadShow = (bfb: number, all: number, index: number) => { },
} = {}): Promise<{
  /**
   * 文件文件
   */
  fileName: string;
  /**
   * 文件大小
   */
  fileSize: string;
  /**
   * 文件唯一值 , 用于访问文件的
   */
  fileEntity: string;
  /**
   * 文件的后缀名
   */
  fileExtension: string
}> {
  //切片文件唯一标识
  let uuid = v4();

  //转化每次切割的字节
  let size = inSize * 1024 * 1024;

  //切割后的文件碎片
  let sectionList: Blob[] = [];

  //将文件进行分割
  //因为 文件对象 继承于 Blob,所以可以使用Blob进行处理
  for (let i = 0; i < file.size; i += size) {
    sectionList.push(file.slice(i, i + size));
  }

  //文件上传队列
  let uploadList = sectionList.map((item, index) => {
    return {
      index: index + 1,
      value: item
    }
  })

  //切片上传时,是否存在错误,如果存在错误,则切断全部上传
  let isError: boolean = false;

  if (parallelCount > 6) parallelCount = 6;
  if (parallelCount < 1) parallelCount = 1;

  return new Promise((resolve, reject) => {
    //表示要同时启动几个上传序列
    for (let i = 0; i < parallelCount; i++) {
      createUploadIn();
    }

    /**
     * 创建一个上传序列
     */
    function createUploadIn() {
      //只有一个上传序列的时候,其实这里永远不会被触发,这里是用于多个并行上传序列准备的,
      //当任意一个上传序列出现错误时候,其他序列都可以暂停上传
      if (isError) return;

      //取出一个文件切片
      let item = uploadList.shift();

      if (!item) {
        //不存在,表示切片已经全部上传完成
        //只有一个上传序列的时候,其实这里永远不会被触发,这里是用于多个并行上传序列准备的
        return;
      }

      let formData = new FormData();

      formData.append("DocType", docType);
      formData.append("ActionType", actionType);
      formData.append("IsCompress", isImage ? 'true' : '');
      formData.append("file", item.value);//添加文件切片
      formData.append("IsShard", 'true');//开启切片上传
      formData.append("ShardUid", uuid);//文件唯一标识
      formData.append('ContentType', file.type);//文件媒体类型
      formData.append('FileName', file.name)//文件名称
      formData.append('ShardCount', `${sectionList.length}`)//分片总数量
      formData.append('ShardNum', `${item.index}`)//本次上传的第几分片

      request("/File/Upload", formData, {
        contentType: "form",
        state: v4().replaceAll("-", ""),
        isError: false
      })
        .then(res => {
          if (item) {
            onUploadShow && onUploadShow(parseFloat(`${((item.index / sectionList.length) * 100).toFixed(2)}`), sectionList.length, item.index);
          }
          if (uploadList.length == 0) {
            //表示切片已经全部上传
            if (res) {
              //存在res,表示当前接口才是切片的最后一片完成了
              //表示已经全部上传完成了
              resolve({
                fileName: res[0].FileName,
                fileSize: res[0].FileLength,
                fileEntity: res[0].FileEntity,
                fileExtension: res[0].FileExtension,
              })
            }
          } else {
            //重新调用
            createUploadIn();
          }
        })
        .catch((data) => {
          if (!isError) {
            isError = true;
            ElNotification({
              title: '错误提示',
              message: `${data.Msg}`,
              type: 'error',
            })
            reject(data);
          }
        })
    }
  })
}


export function upVideo(fileObj: File, docType: string, {
  inSize = 0.5,//分片大小 默认2  单位m
  actionType = "",
  inUnderWayFn = function () { },//进度条改变触发函数
  inUpOverFn = function () { },//上传完成触发函数
} = {}): Promise<{
  inSize: number,
  actionType: string
  inUnderWayFn: null,
  inUpOverFn: null
}> {
  function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  }
  function NewGuid() {
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  }
  let size = inSize * 1024 * 1024
  // let size = inSize
  let file: any = fileObj
  return new Promise((resolve, reject) => {
    upbegin()
    // 上传文件
    function upbegin() {
      let videoTime = videoLong();//视频播放时间

      // 视频分片
      let start = 0, end = 0, chunkArr: any = [];
      function chuli() {
        end += size;
        var blob = file.slice(start, end);
        start += size;
        if (blob.size) {
          chunkArr.push(blob);
          chuli();
        } else {
          return chunkArr
        }
      }
      chuli();

      //预请求接口 然后this.inTurnto(chunkArr); 分片请求
      // 分片请求主体
      inTurnto(chunkArr);
    }
    // 获取视频总时长
    function videoLong() {
      return new Promise((resolve) => {
        var url = URL.createObjectURL(file);
        var audioElement: any = new Audio(url);
        resolve(audioElement)
        // audioElement.addEventListener("loadedmetadata", function() {
        //   var hour:any = parseInt((audioElement.duration) / 3600);
        //   if (hour<10) { hour = "0" + hour; }
        //   var minute = parseInt((audioElement.duration % 3600) / 60);
        //   if (minute<10) {  minute = "0" + minute; }
        //   var second = Math.ceil(audioElement.duration % 60);
        //   if (second<10) { second = "0" + second; }
        //   resolve(hour + ":" + minute + ":" + second)
        // });
      })
    }
    //初始请求的state值，这个值应该是在页面初始化完成后生成一个，然后之后的变更都应该放到ajax完成后去变更state值
    var state = NewGuid().replace(/-/g, '')
    // 多个视频一一请求
    function inTurnto(chunkArr: any) {
      const chunkAllNum = chunkArr.length;//片段总数量        
      let count = 0;//完成个数
      //文件令牌。一堆碎片的统一标识，用于合成文件，所以本次上传多个碎片，用一个标识
      let sharduid = NewGuid()
      let worker = function (index: any) {

        let shardNum = index + 1
        let item = chunkArr[index]
        // let p = new Promise((resolve, reject) => {
        var data = new FormData();
        data.append('DocType', docType)
        data.append('ActionType', "")
        data.append('IsCompress', 'true')//是否压缩/切片/转码
        data.append('IsShard', 'true')//是否分片
        data.append('ShardUid', sharduid)//文件令牌。一堆碎片的统一标识，用于合成文件
        //这里不对
        //data.append('ContentType', item)//文件媒体类型
        //临时写个测试jpg的图片
        data.append('ContentType', file.type)//文件媒体类型
        //追加文件
        data.append(sharduid, item)//文件流
        data.append('FileName', file.name)//文件名
        data.append('ContentLength', file.size)//文件大小
        data.append('ShardCount', chunkAllNum)//分片总数量
        data.append('ShardNum', shardNum)//本次上传的第几分片
        request("/File/Upload", data, {
          contentType: "form",
          state: state
        })
          .then(res => {

            //接口完成后变更一次state值，这才是正确的防重逻辑。
            state = NewGuid().replace(/-/g, '')
            // appAction.resetPageuuid();

            if (shardNum >= chunkAllNum) {
              //分片都传输完成了
              if (res) {
                //得到文件的地址令牌
                //成功
                // alert(JSON.stringify(res.data.Data))
                resolve(res[0])
              }
            } else {
              //分片未传输完成，索引+1，递归调用
              worker(++index)
            }
          })
          .catch()
        // axios.post('http://localhost:5874/File/Upload?state=' + state + '&token=' + token, data).then(res => {
        //     console.log("res", res);
        //     //接口完成后变更一次state值，这才是正确的防重逻辑。
        //     state = this.NewGuid().replace(/-/g, '')
        //     if (res.status == 200) {
        //         if (res.data.Code == '0') {
        //             if (shardNum >= chunkAllNum) {
        //                 //分片都传输完成了
        //                 if (res.data.Data != null) {
        //                     //得到文件的地址令牌
        //                     //成功
        //                     alert(JSON.stringify(res.data.Data))
        //                 } else {
        //                     //报错-服务器错误
        //                     alert('没有获取到合成的文件')
        //                 }
        //             } else {
        //                 //分片未传输完成，索引+1，递归调用
        //                 worker(++index)
        //             }
        //         } else {
        //             //报错-业务错误
        //             alert(res.data.Msg)
        //         }
        //     } else {
        //         //报错-HTTP状态码
        //         alert(res.status)
        //     }
        // }).catch(function (error) {
        //     //报错
        //     console.log(error);
        // });
      }
      //首次开始执行，后面请求成功后再递归调用。这里为什么用递归，因为ajax是异步的，下面的for循环遍历会在一瞬间发起几百个请求，分片上传的意义没了。而且使用递归仍然可以保持ajax的异步特征，不会阻塞后续逻辑。
      worker(0)
    }
  })
}

// export function upVideoOld(fileObj: File, {
//   inSize = 2,//分片大小 默认2  单位m
//   inUnderWayFn = function () { },//进度条改变触发函数
//   inUpOverFn = function () { },//上传完成触发函数
// }) {
//   let file: any = null//文件对象
//   let size = 0//分片大小 kb
//   // let progressBar=0//进度条 num%
//   let underWayFn = null//进度条改变触发函数
//   let upOverFn = null//上传完成触发函数
//   // let t=null//定时器
//   // 初始化函数
//   init()
//   function init() {
//     file = fileObj;
//     size = inSize * 1024 * 1024;
//     underWayFn = inUnderWayFn;
//     upOverFn = inUpOverFn;
//     // 判断是否是满足条件的视频对象 满足条件调用this.upbegin()处理
//     upbegin();
//   }
//   // 上传文件
//   async function upbegin() {
//     let videoTime = await videoLong();//视频播放时间

//     // 视频分片
//     let start = 0, end = 0, chunkArr: any = [];
//     function chuli() {
//       end += size;
//       var blob = file.slice(start, end);
//       start += size;
//       if (blob.size) {
//         chunkArr.push(blob);
//         chuli();
//       } else {
//         return chunkArr
//       }
//     }
//     chuli();
//     console.log("chunkArr", chunkArr);

//     //预请求接口 然后this.inTurnto(chunkArr); 分片请求
//     // 分片请求主体
//     // this.inTurnto(chunkArr);


//     console.log("获取视频总长", videoTime, file)
//   }
//   // 缓慢增长到目标进度条
//   // function changeProgressBar(num:any){
//   //   clearInterval(this.t)
//   //   this.t = setInterval(() => {
//   //     if(this.progressBar == num){
//   //       clearInterval(this.t)
//   //       //上传完成
//   //       if(this.progressBar === 100){
//   //         this.upOverFn();//通知上传完成
//   //         this.clearUpVideo();//格式化重置
//   //       } 
//   //     }else{
//   //       this.progressBar++;
//   //       this.underWayFn(this.progressBar);//改变进度条通知
//   //     }
//   //   }, 50);
//   // }

//   // 多个视频一一请求
//   // function inTurnto(chunkArr:any){
//   //   const chunkAllNum=chunkArr.length;//片段总数量
//   //   let count=0;//完成个数
//   //   chunkArr.forEach( (item:any,index:any) =>{
//   //     // 模拟数据请求
//   //     setTimeout(() => {
//   //       console.log(item,index)
//   //       count++;//增加当前进度
//   //       this.changeProgressBar( parseInt(count/chunkAllNum*100) );//改变进度
//   //     }, 1000);
//   //   })
//   // }
//   // 获取视频总时长
//   function videoLong() {
//     return new Promise((resolve) => {
//       var url = URL.createObjectURL(file);
//       var audioElement: any = new Audio(url);
//       console.log("audioElement.duration", audioElement.duration);
//       // audioElement.addEventListener("loadedmetadata", function() {
//       //   var hour:any = parseInt((audioElement.duration) / 3600);
//       //   if (hour<10) { hour = "0" + hour; }
//       //   var minute = parseInt((audioElement.duration % 3600) / 60);
//       //   if (minute<10) {  minute = "0" + minute; }
//       //   var second = Math.ceil(audioElement.duration % 60);
//       //   if (second<10) { second = "0" + second; }
//       //   resolve(hour + ":" + minute + ":" + second)
//       // });
//     })
//   }
//   // 重置
//   // function clearUpVideo(){
//   //   this.file=null;
//   //   this.size=0;
//   //   this.progressBar=0;
//   //   this.underWayFn=null;
//   //   this.upOverFn=null;
//   //   this.t=null;
//   // },
// }
// 存储
export function setStorage(key: any, value: any, sTime: any) {
  let obj = {
    data: value,
    time: Date.now(),
    storageTime: sTime
  }
  window.localStorage.setItem(key, JSON.stringify(obj))
}
export function getStorage(key: any) {
  let obj: any = window.localStorage.getItem(key)
  obj = JSON.parse(obj)
  if (null == obj || (Date.now() - obj.time > obj.storageTime)) {
    window.localStorage.removeItem(key);
    return null
  }
  return obj.data
}

/**
 *  jsonp跨域请求数据
 */
export function jsonp(url: string) {

  return new Promise((resolve, reject) => {

    // 这里的 "jsonCallBack" ，和调用的 jsonp 的 url 中的 callback 值相对应（见粗体字）

    window.jsonCallBack = (result: any) => {

      resolve(result.data)

    }

    const JSONP = document.createElement('script');

    JSONP.type = 'text/javascript';

    JSONP.src = url;
    document.getElementsByTagName('head')[0].appendChild(JSONP);
    setTimeout(() => {
      document.getElementsByTagName('head')[0].removeChild(JSONP)
    }, 500)

  })

}
/**
 * 将富文本中的图片根路径进行替换
 */
export function HTMLImgRootReplace(htmlstring: string, substr: string, replacement: string) {
  var reg = new RegExp(substr, "g")
  var newstr = htmlstring.replace(reg, replacement);
  return newstr;
}